package com.jason.practice.service;

import com.google.common.collect.Lists;
import com.jason.practice.utils.AbstractExtractionRestUtil;
import com.jason.practice.utils.PageVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.*;

/**
 * 程熙cjp：https://blog.csdn.net/weixin_41133233
 * <p>
 * resetTemplate自定义请求工具类
 * restTemplate 需要请求方注入，因为来自不同服务所以要携带一些自己的信息
 * 远程调用默认返回本项目中自定的ResponseVO类
 *
 * @author chengxi
 * @date 2020/5/30 21:00
 */
@Slf4j
@Component
public class RestTemplateUtil extends AbstractExtractionRestUtil {

    /**
     * Get请求a
     * get请求如果需要携带body传输，请自定义一a个factory，扩展HttpComponentsClientHttpRequestFactory，并在RestTemplateConfig中指定此拓展
     *
     * @param appId             服务id
     * @param apiUrl            访问路径
     * @param requestData       请求参数
     * @param responseBeanClass 返回bean的类型
     * @param restTemplate      注入的RestTemplate
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R extends Object> T requestGet(String appId, String apiUrl, R requestData, Class<T> responseBeanClass, RestTemplate restTemplate) {

        return restTemplate.getForObject(urlCreat(apiUrl), responseBeanClass, requestData);
    }

    /**
     * Post请求
     *
     * @param appId
     * @param apiUrl
     * @param requestData
     * @param responseBeanClass
     * @param restTemplate
     * @param <T>
     * @param <R>
     * @return 返回Bean
     */
    public static <T, R> T requestBeanPost(String appId, String apiUrl, R requestData, Class<T> responseBeanClass, RestTemplate restTemplate) {

        return requestMethodBodyBean(apiUrl, requestData, responseBeanClass, restTemplate, HttpMethod.POST);
    }

    /**
     * Post请求
     *
     * @param apiUrl
     * @param requestData
     * @param responseBeanClass
     * @param restTemplate
     * @param <T>
     * @param <R>
     * @return 返回List<Bean>
     */
    public static <T, R> List<T> requestBeanListPost(String apiUrl, R requestData, Class<T> responseBeanClass, RestTemplate restTemplate) {

        Object responseData = requestMethodBody(apiUrl, requestData, restTemplate, HttpMethod.POST);

        return getResponseDataList(responseData, responseBeanClass);
    }

    /**
     * Post请求
     *
     * @param apiUrl
     * @param requestData
     * @param responseBeanClass
     * @param restTemplate
     * @param <T>
     * @param <R>
     * @return 返回Page<List < Bean>>
     */
    public static <T, R> PageVO<T> requestBeanListPageVoPost(String apiUrl, R requestData, Class<T> responseBeanClass, RestTemplate restTemplate) {

        Map<String, Object> responseMapData = null;
        try {
            Object responseData = requestMethodBody(apiUrl, requestData, restTemplate, HttpMethod.POST);
            if (responseData == null) {
                return null;
            }
            responseMapData = (HashMap<String, Object>) responseData;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("类型转换异常: 分页响应数据转换:{}", e);
            throw new ClassCastException("类型转换异常: 分页响应数据转换");
        }
        Object data = responseMapData.get("data");
        Integer currentPage = (Integer) responseMapData.get("currentPage");
        Integer pageSize = (Integer) responseMapData.get("pageSize");
        int count = (int) responseMapData.get("count");

        List<T> responseDataList = getResponseDataList(data, responseBeanClass);
        return new PageVO<T>(currentPage, pageSize, (long) count, responseDataList);
    }

    /**
     * Post请求
     *
     * @param apiUrl
     * @param requestData
     * @param restTemplate
     * @param <R>
     * @return 返回List(String)
     */
    public static <R> List<String> requestStringListPost(String apiUrl, R requestData, RestTemplate restTemplate) {
        Object responseData = requestMethodBody(apiUrl, requestData, restTemplate, HttpMethod.POST);
        if (responseData == null) {
            return null;
        }

        try {
            if (responseData instanceof List) {
                return (List<String>) responseData;
            } else if (responseData instanceof Set) {
                return new ArrayList<String>((Set) responseData);
            } else if (responseData instanceof String[]) {
                return Arrays.asList((String[]) responseData);
            } else if (responseData instanceof String) {
                return Lists.newArrayList((String) responseData);
            } else if (requestData instanceof Queue) {
                return (List<String>) responseData;
            } else if (requestData instanceof AbstractCollection) {
                return (List<String>) responseData;
            }
        } catch (ClassCastException e) {
            e.printStackTrace();
            log.error("类型转换异常，返回值转换为String类型异常:{}", e);
            throw new ClassCastException("类型转换异常，返回值转换为String类型异常");
        }

        throw new ClassCastException("返回数据类型不是String");

    }

    /**
     * Get请求  无参
     *
     * @param apiUrl
     * @param responseBeanClass
     * @param restTemplate
     * @param <T>
     * @return 返回bean
     */
    public static <T> T requestGet( String apiUrl, Class<T> responseBeanClass, RestTemplate restTemplate) {

        return restTemplate.getForObject(urlCreat(apiUrl), responseBeanClass);
    }

    /**
     * Post请求 无参
     *
     * @param apiUrl
     * @param responseBeanClass
     * @param restTemplate
     * @param <T>
     * @return 返回bean
     */
    public static <T> T requestBeanPost(String apiUrl, Class<T> responseBeanClass, RestTemplate restTemplate) {

        return requestMethodBodyBean(apiUrl, null, responseBeanClass, restTemplate, HttpMethod.POST);
    }

}

